package cn.ilovese.collect.serviceimpl.file;

import cn.ilovese.collect.service.file.FileService;
import cn.ilovese.collect.util.Constant;
import cn.ilovese.collect.vo.ResultVO;
import cn.ilovese.collect.vo.file.FileInfoVO;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService {

    String endpoint = "oss-cn-hangzhou.aliyuncs.com";
    // 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
    String accessKeyId = "LTAI5tC4sbr65Jc1rEArtH9Z";
    String accessKeySecret = "RLryYQcWGlubTWb7ClYOvAF8uODu4w";
    // 填写Bucket名称，例如examplebucket。
    String bucketName = "lluviasnowb01";
    String dir="collect/";

    @Override
    public ResultVO<FileInfoVO> uploadFile(MultipartFile multipartFile) {
        OSS ossClient = null;
        FileInfoVO fileInfoVO=null;
//        try {
//            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
//
//            InputStream inputStream=multipartFile.getInputStream();
//            String originName=multipartFile.getOriginalFilename();
////            InputStream inputStream=new FileInputStream(multipartFile);
////            String originName=multipartFile.getName();
//
//            String type  = originName.substring(originName.lastIndexOf(".")+1);
//            String size = String.format("%.2f", (multipartFile.getSize() * 1.0 / 1024 / 1024)) + " MB";
//
//            String filename= UUID.randomUUID().toString();
//            String suffix=originName.substring(originName.indexOf("."));
//            String newName=filename+suffix;
//            String fileUrl="collect/"+newName;
//            ossClient.putObject(bucketName,fileUrl,inputStream);
//
//            //return "https://"+bucketName+"."+endpoint+"/"+fileUrl;
//            fileInfoVO=new FileInfoVO(newName, type, size);
//
//
//            return new ResultVO<>(Constant.REQUEST_SUCCESS, "文件上传成功", fileInfoVO);
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            return new ResultVO<>(-1, "文件上传失败");
//        } finally {
//            if (ossClient != null) {
//                ossClient.shutdown();
//            }
//        }
        try {
            String originName=multipartFile.getOriginalFilename();
            System.err.println(originName);
            String type  = originName.substring(originName.lastIndexOf(".")+1);
            String filename= UUID.randomUUID().toString();
            String suffix=originName.substring(originName.indexOf("."));
            String newName=filename+suffix;
            String objectName="collect/"+newName;
            // 创建InitiateMultipartUploadRequest对象。
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);

            // 初始化分片。
            InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
            // 返回uploadId，它是分片上传事件的唯一标识。您可以根据该uploadId发起相关的操作，例如取消分片上传、查询分片上传等。
            String uploadId = upresult.getUploadId();

            // partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
            List<PartETag> partETags =  new ArrayList<PartETag>();
            // 每个分片的大小，用于计算文件有多少个分片。单位为字节。
            final long partSize = 1 * 1024 * 1024L;   //1 MB。

            // 填写本地文件的完整路径。如果未指定本地路径，则默认从示例程序所属项目对应本地路径中上传文件。

            long fileLength = multipartFile.getSize();
            int partCount = (int) (fileLength / partSize);
            System.err.println(partCount);
            System.err.println(partSize);
            if (fileLength % partSize != 0) {
                partCount++;
            }
            // 遍历分片上传。
            for (int i = 0; i < partCount; i++) {
                long startPos = i * partSize;
                long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
                InputStream instream=multipartFile.getInputStream();
                // 跳过已经上传的分片。
                instream.skip(startPos);
                UploadPartRequest uploadPartRequest = new UploadPartRequest();
                uploadPartRequest.setBucketName(bucketName);
                uploadPartRequest.setKey(objectName);
                uploadPartRequest.setUploadId(uploadId);
                uploadPartRequest.setInputStream(instream);
                // 设置分片大小。除了最后一个分片没有大小限制，其他的分片最小为100 KB。
                uploadPartRequest.setPartSize(curPartSize);
                // 设置分片号。每一个上传的分片都有一个分片号，取值范围是1~10000，如果超出此范围，OSS将返回InvalidArgument错误码。
                uploadPartRequest.setPartNumber( i + 1);
                // 每个分片不需要按顺序上传，甚至可以在不同客户端上传，OSS会按照分片号排序组成完整的文件。
                UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
                // 每次上传分片之后，OSS的返回结果包含PartETag。PartETag将被保存在partETags中。
                partETags.add(uploadPartResult.getPartETag());
            }


            // 创建CompleteMultipartUploadRequest对象。
            // 在执行完成分片上传操作时，需要提供所有有效的partETags。OSS收到提交的partETags后，会逐一验证每个分片的有效性。当所有的数据分片验证通过后，OSS将把这些分片组合成一个完整的文件。
            CompleteMultipartUploadRequest completeMultipartUploadRequest =
                    new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);


            // 完成分片上传。
            CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
            System.out.println(completeMultipartUploadResult.getETag());
            String size = String.format("%.2f", (multipartFile.getSize() * 1.0 / 1024 / 1024)) + " MB";
            fileInfoVO=new FileInfoVO(newName, type, size);
            return new ResultVO<>(Constant.REQUEST_SUCCESS, "文件上传成功", fileInfoVO);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO<>(-1, "文件上传失败");
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    @Override
    public void downloadFile(String fileName, HttpServletResponse response) {
        String objectName =dir+fileName;

        // 创建OSSClient实例。
//        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
//        ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File("C:\\Users\\apple\\Desktop\\tmp\\try\\a.md"));
//        try {
//            // 调用ossClient.getObject返回一个OSSObject实例，该实例包含文件内容及文件元信息。
//            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
//
//            // 调用ossObject.getObjectContent获取文件输入流，可读取此输入流获取其内容。
//            InputStream content = ossObject.getObjectContent();
//            if (content != null) {
//                BufferedReader reader = new BufferedReader(new InputStreamReader(content));
//                while (true) {
//                    String line = reader.readLine();
//                    if (line == null) break;
//                    System.out.println("\n" + line);
//                }
//                // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
//                content.close();
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            if (ossClient != null) {
//                ossClient.shutdown();
//            }
//        }
        try {

            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            InputStream is =ossClient.getObject(bucketName,dir+fileName).getObjectContent();
            //AliOssCloudUtil ossClientUtil = new AliOssCloudUtil();
            //InputStream is = ossClientUtil.getInputStreamByFileUrl(ossClientUtil.getFiledir() + fileName);
            // 配置文件下载
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            // 下载文件能正常显示中文
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            OutputStream os = response.getOutputStream();
            byte[] b = new byte[1024];
            int len = -1;
            while ((len = is.read(b)) != -1) {
                os.write(b, 0, len);
            }
            is.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    // @Resource标识特定的目标组件，你们自己添加，类似软工二
    // @Autowired装载java bean，用于set方法，你们自己添加，类似软工二
    //注意在这里添加每个实现方法的说明注释，类似以下
    /**
     * 这个方法干了什么
     *
     * @param 参数1 解释
     * @param 参数2 解释
     * ......
     * @return 返回值解释
     */
}
